#pragma once

#include<iostream>
#include<fstream>
#include <atomic>
#include<vector>
#include <sys/time.h>
#include <sys/stat.h>
#include<boost/algorithm/string.hpp>
#include"spdlog.hpp"

const std::string temp_path="../temp/";
namespace y_util
{
    //时间创造唯一性
    class TimeUtil
    {
    public:
        /********************************
         * timeval结构体通常包含两个成员：
         * tv_sec：时间的秒部分。
         * tv_usec：时间的微秒部分。
         ********************************/
        
        static std::string GetTimeMs()
        {
            struct timeval _time;
            gettimeofday(&_time,nullptr);
            return std::to_string(_time.tv_sec*1000+_time.tv_usec/1000);
        }
    };

    //生成文件类
    class PathUtil
    {
    public:
        //生成编译文件名
        static std::string Cpp(const std::string& file_name)
        {
            return AddSuffix(file_name,".cpp");
        }
        //生成错误文件名
        static std::string Compile_error(const std::string& file_name)
        {
            return AddSuffix(file_name,".compile_error");
        }
        ////生成可执行文件名
        static std::string Exe(const std::string& file_name)
        {
            return AddSuffix(file_name,".exe");
        }

        //生成运行时需要的临时文件名
        static std::string Stdin(const std::string& file_name)
        {
            return AddSuffix(file_name,".stdin");
        }
        static std::string Stdout(const std::string& file_name)
        {
            return AddSuffix(file_name,".stdout");
        }
        static std::string Stderr(const std::string& file_name)
        {
            return AddSuffix(file_name,".stderr");
        }

    private:
        //为文件名添加后缀
        static std::string AddSuffix(const std::string& file_name,const std::string& suffix)
        {
            return temp_path+file_name+suffix;
        }
    };

    //文件操作类
    class FileUtil
    {
    public:
        static bool IsFileExists(const std::string& path_name)
        {
            //struct stat 是一个在 POSIX 系统（如 Linux 和 macOS）中定义的结构体，用于存储文件的状态信息。
            //它通常用于系统调用（如 stat()、fstat() 和 lstat()）中，以获取文件的元数据。
            struct stat st;
            //stat(const char* path, struct stat* buf)：获取指定路径的文件状态信息。把信息存储在st中
            if(stat(path_name.c_str(),&st)==0) return true;//0表示，成功获取
            //-1表示没有此文件
            return false;
        } 

        static std::string UniqueFileName()
        {
            // 毫秒级时间戳+原子性递增唯一值: 来保证唯一性
            static std::atomic_uint id(0);
            id++;
            std::string ms=TimeUtil::GetTimeMs();
            std::string unique_id=std::to_string(id);
            return ms+"_"+unique_id;
        }

        static bool WriteFile(const std::string& target,const std::string &content)
        {
            //如果文件不存在，它会创建一个新文件；如果文件存在，它会覆盖原有内容(流写入)
            std::ofstream out(target);
            if(!out.is_open())
            {
                ERROR("{}文件打开失败",target);
                return false;
            }

            out.write(content.c_str(),content.size());
            out.close();
            return true;
        }

        static bool ReadFile(const std::string &target, std::string *content, bool keep = false)
        {
            (*content).clear();

            std::ifstream in(target);
            if(!in.is_open())
            {
                ERROR("{}文件打开失败",target);
                return false;
            }

            std::string line;
            while(std::getline(in,line))
            {
                (*content)+=line;
                (*content)+=(keep?"\n":"");
            }
            in.close();
            return true;
        }
    };

    class StringUtil
    {
    public:
        static void SqlitString(const std::string& str,std::vector<std::string>* target,const std::string& sep)
        {
            /*********************************************************************************
             * 1、boost::split 是 Boost 库中 boost::algorithm 模块提供的一个函数，用于将字符串分割成多个子字符串，并存储到一个容器中
             * 2、boost::is_any_of 会检查输入字符串中的每个字符是否在 sep 中出现，如果出现，则认为该字符是一个分隔符。
             * 3、boost::algorithm::token_compress_on：这是一个标志，表示在分割时会压缩连续的分隔符
             **********************************************************************************/
            boost::split((*target),str,boost::is_any_of(sep),boost::algorithm::token_compress_on);
        } 
    };
}
